package server.servlet;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import json.JSONObjectWrapper;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import server.database.AbstractTable;
import server.database.DatabaseColumn;
import server.database.query.IQueryResult;
import utils.StringUtils;

import com.google.common.collect.Lists;

public abstract class AbstractEntityServlet extends AbstractServlet
{
	private static final long serialVersionUID = -4758159380873104108L;

	protected abstract String getEntityName();

	protected abstract String getEntitiesName();

	@Override
	protected void doGetSpecific(HttpServletRequest request, HttpServletResponse response, JSONObject output) throws ServletException, IOException
	{
		IQueryResult queryResult = null;

		List<DatabaseColumn> lstFields = Lists.newArrayList();
		List<String> lstValues = Lists.newArrayList();

		String sID = request.getParameter(getTable().ID);
		if (StringUtils.isEmpty_DB(sID))
		{
			setSpecificGetQuery(request, lstFields, lstValues);

			queryResult = getTable().getAllEntities(lstFields, lstValues, AbstractTable.AND);
			output.put(QUERY_RESULT, queryResult.getResult());
		}
		else
		{
			queryResult = querySpecificID(request, lstFields, lstValues);
			output.put(QUERY_RESULT, queryResult.getResult());
		}

		if (queryResult.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);

			JSONArray entities = new JSONArray();
			buildEntityValues(queryResult.getResultValues(), entities, getTable());

			getMultipleTables(entities);

			output.put(getEntitiesName(), entities);

		}
		else if (queryResult.getResult() != IQueryResult.NO_RESULTS)
		{
			setFail(output, UNEXPECTED_ERROR, UNEXPECTED_ERROR);
		}
		else
		{
			output.put(RESULT, false);
			output.put(QUERY_RESULT, IQueryResult.NO_RESULTS);
		}
	}

	protected IQueryResult querySpecificID(HttpServletRequest request, List<DatabaseColumn> lstFields, List<String> lstValues)
	{
		return null;
	}

	protected void setSpecificGetQuery(HttpServletRequest request, List<DatabaseColumn> lstFields, List<String> lstValues)
	{

	}

	@Override
	protected final void doPostSpecific(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		String sRequestType = request.getStringValue(REQUEST_TYPE);

		if (sRequestType.equals(ADD))
		{
			doAddPost(request, output);
		}
		else if (sRequestType.equals(UPDATE))
		{
			doUpdatePost(request, output);
		}
		else if (sRequestType.equals(DELETE))
		{
			doDeletePost(request, output);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, UNKNOWN_TYPE + sRequestType);
		}
	}

	protected void doDeletePost(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		String sID = request.getStringValue(getTable().ID);
		IQueryResult result = getTable().deleteID(sID);

		doDeletePostSpecific(request);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			boolean bDeleteResult = deleteMultipleTables(sID);
			output.put(RESULT, bDeleteResult);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	protected void doAddPost(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		JSONObjectWrapper entity = request.getJsonValue(getEntityName());

		Map<DatabaseColumn, String> mpValues = parseEntityValues(entity, getTable());
		doAddPostSpecific(request, mpValues);

		IQueryResult result = getTable().insert(mpValues);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			int iID = result.getAutoIncrementedValue();
			boolean bAddResult = addMultipleTables(entity, iID);
			output.put(RESULT, bAddResult);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	protected void getMultipleTables(JSONArray entities)
	{
	}

	protected boolean addMultipleTables(JSONObjectWrapper entity, int iID)
	{
		return true;
	}

	protected boolean deleteMultipleTables(String sID)
	{
		return true;
	}

	protected boolean updateMultipleTables(JSONObjectWrapper entity, String sID)
	{
		return true;
	}

	protected void doDeletePostSpecific(JSONObjectWrapper request)
	{
	}

	protected void doUpdatePost(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		JSONObjectWrapper entity = request.getJsonValue(getEntityName());
		String sID = entity.getStringValue(getTable().ID);

		Map<DatabaseColumn, String> mpValues = parseEntityValues(entity, getTable());
		doUpdatePostSpecific(request, mpValues);

		IQueryResult result = getTable().update(sID, mpValues);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			boolean bUpdateResult = updateMultipleTables(entity, sID);
			output.put(RESULT, bUpdateResult);

		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	protected void doAddPostSpecific(JSONObjectWrapper request, Map<DatabaseColumn, String> mpValues)
	{
	}

	protected void doUpdatePostSpecific(JSONObjectWrapper request, Map<DatabaseColumn, String> mpValues)
	{
	}
}
